package com.zzyl.nursing.job;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.net.ServerSocket;
import java.time.Duration;

@Slf4j
@Component
public class ContractJob {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    private static final String LOCK_KEY = "lock:contractJob";
    private static final String CONTRACT_KEY = "contract:";

    @Scheduled(cron = "0 * * * * ?")
    public void contractJob() {

        /**
         * true：表示操作成功，且键（key）原本不存在，成功设置了值。
         * false：表示操作成功，但键（key）已经存在，因此未设置新值。
         */
        int port = 0;
        Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(LOCK_KEY, CONTRACT_KEY);
        try {
            port = new ServerSocket(0).getLocalPort();
            if (flag) {
                //获取当前服务端口

                log.info("==服务端口:" + port + "执行定时任务==");
            } else {
                log.info("==服务端口:" + port + "执行失败==");
            }

            //线程睡眠1分钟
            Thread.sleep(60000);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            //释放锁
            //为了避免程序运行一半出现意外,导致无法释放锁,可以给key添加过期时间,一般设置为定时任务的时间长度一致
            //又为了避免程序执行时间超过了过期时间(上一个服务线程还未执行完毕, 但锁释放了, 下一个线程就会进来操作同一个数据了),
            //所以给key加上续期策略, 使用Redsion框架实现
            stringRedisTemplate.delete(LOCK_KEY);
        }

    }

}
